package com.eling.elcms.travel.service.impl;

import com.eling.elcms.basedoc.model.*;
import com.eling.elcms.basedoc.model.Room.Status;
import com.eling.elcms.basedoc.service.IBusinessMessageManager;
import com.eling.elcms.basedoc.service.IRoomManager;
import com.eling.elcms.core.AppContext;
import com.eling.elcms.core.service.impl.GenericManagerImpl;
import com.eling.elcms.core.util.PropertyUtils;
import com.eling.elcms.system.model.CommonUser;
import com.eling.elcms.travel.dao.IGroupReserveDao;
import com.eling.elcms.travel.model.*;
import com.eling.elcms.travel.model.CheckInImplement.CheckStatus;
import com.eling.elcms.travel.model.CheckInImplement.DataSource;
import com.eling.elcms.travel.model.GroupReserve.CheckInType;
import com.eling.elcms.travel.model.PlanItemGroup.CheckInStatus;
import com.eling.elcms.travel.model.view.GroupReserveSaveView;
import com.eling.elcms.travel.model.view.GroupReserveSignUpView;
import com.eling.elcms.travel.model.view.GroupReserveView;
import com.eling.elcms.travel.model.view.RoomView;
import com.eling.elcms.travel.service.*;
import com.eling.elcms.travel.util.DateHandlerUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class GroupReserveManagerImpl extends GenericManagerImpl<GroupReserve, Long> implements IGroupReserveManager {

	IGroupReserveDao groupReserveDao;

	@Autowired
	private IRoomManager roomManager;

	@Autowired
	private IRoomOccupancyManager roomOccupancyManager;

	@Autowired
	private IRoomRegisterManager roomRegisterManager;

	@Autowired
	private IDestnBuildingManager destnBuildingManager;

	@Autowired
	private IPlanItemGroupManager planItemGroupManager;

	@Autowired
	private ICheckInImplementManager cIImplementM;

	@Autowired
	private ISignUpRegisterManager signUpRegisterManager;

	@Autowired
	private IPlanManager planManager;
	
	@Autowired
 	private IBusinessMessageManager businessMessageManager;
	
	@Autowired
	public void setGroupReserveDao(IGroupReserveDao groupReserveDao) {
		this.dao = groupReserveDao;
		this.groupReserveDao = groupReserveDao;
	}
	
	@Override
	public void rid(RoomRegister roomRegister, GroupReserve groupReserve) {
		groupReserve.getRoomRegisters().remove(roomRegister);
		save(groupReserve);
		roomRegister.getRoom().setStatus(Status.Clear);
		roomRegisterManager.remove(roomRegister.getPkRoomRegister());
		RoomOccupancy room=new RoomOccupancy();
		room.setRoom(roomRegister.getRoom());
		room.setPlanItemGroup(groupReserve.getPlanItemGroup());
		roomOccupancyManager.remove(roomOccupancyManager.query(room));
	}
	
	@Override
	public GroupReserve saveRoom(GroupReserve cond, Room room) {
		room=roomManager.query(room).get(0);
		Set<RoomOccupancy> set=new HashSet<RoomOccupancy>();
		// 时间段
		Set<Date> dateSet = DateHandlerUtil.timeOfDaysByTwoDate(cond.getCheckInDate(),cond.getCheckOutDate());
		for (Date de : dateSet) {
			RoomOccupancy roomOccupancy=new RoomOccupancy();
			room.setStatus(Status.Appoint);
			roomOccupancy.setRoom(room);
			roomOccupancy.setPlanItemGroup(cond.getPlanItemGroup());
			roomOccupancy.setOccupyDate(de);
			roomOccupancy.setVersion(0);
			set.add(roomOccupancy);
		}
		List<RoomOccupancy> list=roomOccupancyManager.save(new ArrayList<RoomOccupancy>(set));
		Set<RoomRegister> roomSet=cond.getRoomRegisters().size()>0?cond.getRoomRegisters():new HashSet<>();
		RoomRegister roomRegister=new RoomRegister();
		roomRegister.setRoomStatus(RoomRegister.RoomStatus.NoCheckIn);
		roomRegister.setRoom(list.get(0).getRoom());
		roomSet.add(roomRegister);
		cond.setRoomRegisters(roomSet);
		return save(cond);
	}

	/**
	 * 组团预约查询列表
	 * 
	 * @param cond
	 * @return
	 * @author zhoulin
	 */
	@Override
	public List<GroupReserveView> queryGroupReservr(GroupReserveView view) {
		List<GroupReserveView> returnList = new ArrayList<GroupReserveView>();
		List<PlanItemGroup> planItemGroupList = planItemGroupManager.query(view.getPlanItemGroup());
		if (!planItemGroupList.isEmpty()) {
			List<Long> pkpigList = planItemGroupList.stream().map(a -> a.getPkPlanItemGroup())
					.collect(Collectors.toList());

			// 查询本团的报名登记
			SignUpRegister sur = new SignUpRegister();
			PropertyUtils.setProperty(sur, "validatePrivilege", false);
			PropertyUtils.setProperty(sur, "planItemGroup.pkPlanItemGroupIn", pkpigList);
			List<SignUpRegister> surList = signUpRegisterManager.query(sur);

			// 查询本团的预约
			GroupReserve gr = new GroupReserve();
			PropertyUtils.setProperty(gr, "planItemGroup.pkPlanItemGroupIn", pkpigList);
			PropertyUtils.setProperty(gr, "checkInTypeIn",
					PropertyUtils.getProperty(view.getGroupReserve(), "checkInTypeIn"));
			List<GroupReserve> grList = query(gr);

			for (PlanItemGroup pig : planItemGroupList) {
				GroupReserveView grv = new GroupReserveView();
				grv.setPlanItemGroup(pig);
				Integer signUpNumber = 0;
				for (SignUpRegister sur1 : surList) {
					if (sur1.getPlanItemGroup().getPkPlanItemGroup().equals(pig.getPkPlanItemGroup())
							&& (sur1.getExitGroup() == null || !sur1.getExitGroup())) {
						signUpNumber += 1;
					}
				}
				for (GroupReserve gr1 : grList) {
					if (gr1.getPlanItemGroup().getPkPlanItemGroup().equals(pig.getPkPlanItemGroup())) {
						grv.setGroupReserve(gr1);
					}
				}
				grv.setSignUpNumber(signUpNumber);

				returnList.add(grv);
			}
		}

		// 过滤掉整团取消的数据
		List<GroupReserveView> views = new ArrayList<GroupReserveView>();
		for (GroupReserveView groupView : returnList) {
			Set<AdjustType> set = groupView.getPlanItemGroup().getAdjustTypes();
			if (!set.isEmpty()) {// 调整
				for (AdjustType type : set) {
					if (!type.name().equals(AdjustType.Abolished.name())) {
						views.add(groupView);
						break;
					}
				}
			} else {// 没调整
				views.add(groupView);
			}

		}
		
		List<Long> pkList = new ArrayList<Long>();//planItem的pk
		for(GroupReserveView groupView :views){
			pkList.add(groupView.getPlanItemGroup().getPlanItem().getPkPlanItem());
		}
		
		Plan p = new Plan();
		p.setOrganization(((CommonUser)AppContext.curUser()).getOrganization());
		List<Plan> lists = planManager.query(p);
		for(GroupReserveView groupView :views){
			PlanItem planItem = groupView.getPlanItemGroup().getPlanItem();
			for(Plan plan : lists){
				Set<PlanItem> ts = plan.getPlanItem();
				for(PlanItem item : ts){
					if(item.getPkPlanItem().equals(planItem.getPkPlanItem())){
						groupView.setPlanTitle(plan.getPlanTitle());
						groupView.setVerNumber(plan.getVerNumber());
					}
				}
			}
		}
		Collections.sort(views,new Comparator<GroupReserveView>() {
			public int compare(GroupReserveView o1, GroupReserveView o2) {
				Date date1 = o1.getPlanItemGroup().getPlanItem().getStartDate();
				Date date2 = o2.getPlanItemGroup().getPlanItem().getStartDate();
				return date1.compareTo(date2);
			};
		});
		return views;
	}

	/**
	 * 查询房间状态
	 * 
	 * @param pkOrgBuilding
	 * @param pkRoomType
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	@Override
	public List<RoomView> queryRoom(Long pkOrgBuilding, Long pkRoomType, Date startDate, Date endDate) {
		List<RoomView> returnList = new ArrayList<>();
		Room roomCond = new Room();
		PropertyUtils.setProperty(roomCond, "orgBuilding.pkOrgBuilding", pkOrgBuilding);
		PropertyUtils.setProperty(roomCond, "roomType.pkRoomType", pkRoomType);
		// 查询指定楼宇和房型的所有房间
		List<Room> roomList = roomManager.query(roomCond);
		if (!roomList.isEmpty()) {
			for (Room r : roomList) {
				RoomView rv = new RoomView();
				rv.setPkRoom(r.getPkRoom());
				rv.setCode(r.getCode());
				rv.setRoomStatus(RoomStatus.Free);
				returnList.add(rv);
			}
		}
		// 查询预约后登记的房间
		List<RoomView> rgList = groupReserveDao.queryRoom(pkOrgBuilding, pkRoomType);
		if (!returnList.isEmpty()) {
			// 如果房间是同一个证明在房间登记中已登记了该房间，将房间登记的pk加入
			for (RoomView rv1 : returnList) {
				for (RoomView rv2 : rgList) {
					if (rv1.getPkRoom().equals(rv2.getPkRoom())) {
						rv1.setPkRoomRegister(rv2.getPkRoomRegister());
						break;
					}
				}
			}
			// 如果房间登记数据为空，证明需要查询状态，否则返回所有房间
			if (!rgList.isEmpty()) {
				Set<Long> pkReserverSet = new HashSet<>(
						groupReserveDao.queryRoomStatus(pkOrgBuilding, pkRoomType, startDate, endDate, false));
				Set<Long> pkUseSet = new HashSet<>(
						groupReserveDao.queryRoomStatus(pkOrgBuilding, pkRoomType, startDate, endDate, true));
				for (RoomView rv : returnList) {
					rv.setRoomStatus(pkUseSet.contains(rv.getPkRoomRegister()) ? RoomStatus.InUse
							: pkReserverSet.contains(rv.getPkRoomRegister()) ? RoomStatus.Reserve : RoomStatus.Free);
				}
			}
		}

		return returnList;
	}

	/**
	 * 根据组团目的地查询楼宇
	 * 
	 * @param pkDestination
	 * @return
	 * @author zhoulin
	 */
	@Override
	public List<OrgBuilding> queryBuildingByDes(Long pkDestination) {
		DestnBuilding desB = new DestnBuilding();
		PropertyUtils.setProperty(desB, "destination.pkDestination", pkDestination);
		PropertyUtils.setProperty(desB, "fetchProperties", "orgBuilding.pkOrgBuilding,orgBuilding.name");
		List<DestnBuilding> desBList = destnBuildingManager.query(desB);
		List<OrgBuilding> returnList = new ArrayList<OrgBuilding>();
		if (!desBList.isEmpty()) {
			returnList = desBList.stream().map(a -> a.getOrgBuilding()).collect(Collectors.toList());
		}
		return returnList;
	}

	@Override
	public GroupReserveSignUpView queryAll(GroupReserve cond) {
		String fetchProperties = PropertyUtils.getProperty(cond, "fetchProperties");
		PropertyUtils.setProperty(cond, "fetchProperties", null);
		GroupReserve gr = super.query(cond).get(0);
		GroupReserveSignUpView grsuv = new GroupReserveSignUpView();
		PropertyUtils.setProperty(grsuv, "fetchProperties", fetchProperties);

		// 根据组团预约查询报名
		SignUpRegister sr = new SignUpRegister();
		sr.setPlanItemGroup(gr.getPlanItemGroup());
		List<SignUpRegister> list = signUpRegisterManager.query(sr);
		List<SignUpRegister> signList = new ArrayList<>();
		for (SignUpRegister signUpRegister : list) {
			if (signUpRegister != null && (signUpRegister.getExitGroup() == null || !signUpRegister.getExitGroup())) {
				signList.add(signUpRegister);
			}
		}
		grsuv.setGroupReserve(gr);
		grsuv.setSignUpRegisters(signList);
		return grsuv;
	}

	/**
	 * 组团预约保存视图
	 * 
	 * @param grsView
	 * @return
	 * @author zhoulin
	 */
	@Override
	public GroupReserve saveAll(GroupReserveSaveView grsView) {
		GroupReserve groupReserve = grsView.getGroupReserve();
		List<RoomRegister> rrSaveList = new ArrayList<>();
		if (grsView.getGroupReserve().getCheckInType().equals(CheckInType.Organization)) {
			List<RoomRegister> rrList = grsView.getRrList();

			List<Long> pkList = new ArrayList<>();
			for (RoomRegister room : rrList) {
				if (null != room.getPkRoomRegister()) {
					pkList.add(room.getPkRoomRegister());
				} else {
					room.setRoomStatus(RoomRegister.RoomStatus.NoCheckIn);
					room.getRoom().setStatus(Status.Appoint);
					rrSaveList.add(room);
				}
			}
			if (!pkList.isEmpty()) { // 解决懒加载
				RoomRegister rrCond = new RoomRegister();
				PropertyUtils.setProperty(rrCond, "pkRoomRegisterIn", pkList);
				List<RoomRegister> rrCondList = roomRegisterManager.query(rrCond);
				for (RoomRegister rr2 : rrCondList) {
					RoomRegister saveRR = new RoomRegister();
					saveRR.setRoomStatus(RoomRegister.RoomStatus.NoCheckIn);
					rr2.getRoom().setStatus(Status.Appoint);
					saveRR.setRoom(rr2.getRoom());
					rrSaveList.add(saveRR);
				}
			}
			rrSaveList = roomRegisterManager.save(rrSaveList);

			// 时间段
			Set<Date> dateSet = DateHandlerUtil.timeOfDaysByTwoDate(groupReserve.getCheckInDate(),
					groupReserve.getCheckOutDate());
			// 回写
			Set<RoomOccupancy> roomOccupancySet = new HashSet<>();
			for (RoomRegister rr : rrSaveList) {
				for (Date de : dateSet) {
					RoomOccupancy ro = new RoomOccupancy();
					ro.setRoom(rr.getRoom());
					ro.setPlanItemGroup(groupReserve.getPlanItemGroup());
					ro.setOccupyDate(de);
					ro.setVersion(0);
					roomOccupancySet.add(ro);
				}
			}

			// 保存房间占用数据
			if (!roomOccupancySet.isEmpty()) {
				roomOccupancyManager.save(new ArrayList<>(roomOccupancySet));
			}

		}

		groupReserve = save(groupReserve);
		if (grsView.getGroupReserve().getCheckInType().equals(CheckInType.Alliance)) {
			businessMessageManager.saveBusinessMessage(new BusinessMessage(TargetType.Role,TaskType.AllianceConfirm,groupReserve.getPkGroupReserve()));

		}
		if (!rrSaveList.isEmpty()) {
			Set<RoomRegister> rrSet = new HashSet<>(rrSaveList);
			groupReserve.setRoomRegisters(rrSet);
			groupReserve = save(groupReserve);
		}
		// 回写团状态
		PlanItemGroup planItemGroup = groupReserve.getPlanItemGroup();
		planItemGroup.setCheckInStatus(CheckInStatus.Reserve);
		planItemGroupManager.save(planItemGroup);

		// 如果入住直属机构则推入住准备落实单
		if (grsView.getGroupReserve().getCheckInType().equals(CheckInType.Organization)) {
			CheckInImplement cii = new CheckInImplement();
			cii.setGroupReserve(groupReserve);
			cii.setServicePoint(groupReserve.getPlanItemGroup().getServicePoint());
			cii.setDataSource(DataSource.GroupReserve);
			cii.setStatus(CheckStatus.Initial);
			cii.setConfirmStatus(CheckInImplement.ConfirmStatus.NoConfirm);
			cii.setVersion(0);
			cIImplementM.save(cii);
		}

		return groupReserve;
	}

	@Override
	public List<GroupReserve> queryplanItem(GroupReserve cond) {
		List<GroupReserve> returnlist = new ArrayList<GroupReserve>();
		List<GroupReserve> list = query(cond);
		for (GroupReserve groupReserve : list) {
			if (!groupReserve.getPlanItemGroup().getAdjustTypes().isEmpty()) {// 调整
				for (AdjustType adjustType : groupReserve.getPlanItemGroup().getAdjustTypes()) {
					if (!adjustType.name().equals(AdjustType.Abolished.name())) {
						returnlist.add(groupReserve);
						break;
					}
				}
			} else {// 没调整
				returnlist.add(groupReserve);
			}
		}
		List<GroupReserve> groupList = new ArrayList<>();
		for (GroupReserve groupReserve : returnlist) {
			if (groupReserve.getPlanItemGroup().getSignUpNum() > 0) {
				groupList.add(groupReserve);
			}
		}
		return groupList;
	}

}